﻿#include "string.h"


th::string::string(const char* str)
	: _size(0)
	, _capacity(0)
	, _str(nullptr)
{
	_size = strlen(str);
	_capacity = _size+1;
	_str = new char[_capacity];

	strcpy(_str, str);
}

th::string::string(const string& str)
{
	string temp(str._str);

	std::swap(_str, temp._str);
	std::swap(_size, temp._size);
	std::swap(_capacity, temp._capacity);
}

th::string& th::string::operator=(string& str)
{
	_str = str._str;
	_size = str._size;;
	_capacity = str._capacity;

	return *this;
}

th::string::~string()
{
	delete[] _str;
	_str = nullptr;
	_size = 0;
	_capacity = 0;
}

char* th::string::begin() const
{
	return _str;
}
char* th::string::end() const
{
	return _str + _size;
}

char* th::string::begin() 
{
	return _str;
}
char* th::string::end()
{
	return _str + _size;
}


std::ostream& th::operator<<(std::ostream& out, const th::string& str)
{
	for (auto e : str)
	{
		out << e;
	}

	return out;

}

char& th::string::operator[](int index)
{
	assert(index >= 0 && index <= _size);
	return *(_str + index);
}

void th::string::insert(int index, char ch)
{
	assert(index >= 0 && index <= _size);
	if (_size+1 == _capacity)
	{
		size_t newCapacity = _capacity == 0 ? INITIAL_CAPACITY : _capacity * EXPANSION_FACTOR;
		reserve(newCapacity);
	}
	for (int i = _size-1; i >= index; i--)
	{
		_str[i+1] = _str[i];
	}

	_str[index] = ch;
	_size++;
}

void th::string::reserve(size_t n)
{
	if (n > _capacity)
	{
		_capacity = n;
		char* tmp = new char[_capacity];
		strcpy(tmp, _str);
		delete[] _str;
		_str = tmp;
	}
}

void th::string::append(const char* str)
{
	if (_size + 1 + strlen(str) >= _capacity)
	{
		size_t newCapacity = (_size + 1 + strlen(str)) * EXPANSION_FACTOR;
		reserve(newCapacity);
	}
	strcpy(_str + _size, str);
	_size += strlen(str);
}

th::string& th::string::operator+=(const char* str)
{
	append(str);
	return *this;
}

void th::string::push_back(char ch)
{
	if (_size + 2 >= _capacity)
	{
		size_t newCapacity = (_size + 2) * EXPANSION_FACTOR;
		reserve(newCapacity);
	}
	_str[_size] = ch;
	_str[_size + 1] = '\0';
	_size++;
}

void th::string::append(const char ch)
{
	push_back(ch);
}

th::string& th::string::operator+=(const char ch)
{
	push_back(ch);
	return *this;
}

void th::string::erase(size_t pos, size_t len)
{
	assert(pos < _size && pos >= 0);
	assert(len >= 0);
	if (pos + len >= _size)
	{
		_str[pos] = '\0';
		_size = pos;
	}
	else
	{
		strcpy(_str + pos, _str + pos + len);
		_size -= len;
	}
}